package com.dynamic.data.permission.interceptor;

import com.dynamic.data.permission.annotation.PublicApi;
import com.dynamic.data.permission.config.PermissionProperties;
import com.dynamic.data.permission.model.UserContextHolder;
import com.dynamic.data.permission.model.UserInfoContext;
import com.dynamic.data.permission.rpc.UserServerRpc;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 请求拦截器
 */
@Slf4j
@Component
public class RequestInterceptor implements HandlerInterceptor {

    public static final String TOKEN_HEADER = "identifies";

    @Autowired
    private ServerProperties serverProperties;

    private String prefix;

    @Autowired
    private PermissionProperties permissionProperties;

    @PostConstruct
    private void init() {
        // 获取后端接口起始路径
        prefix = serverProperties.getServlet().getContextPath() + permissionProperties.getPrefix();
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        if (RequestMethod.OPTIONS.name().equals(request.getMethod())) {
            response.setHeader("Access-control-Allow-Origin", request.getHeader("Origin"));
            response.setHeader("Access-Control-Allow-Methods", request.getMethod());
            response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
            response.setStatus(HttpStatus.OK.value());
            return true;
        } else if (!request.getRequestURI().startsWith(prefix) || !needLogin(handler)) {
            // 跳过 非后端接口请求 以及 不需要登录接口请求
            return true;
        }
        return check(handler, request, response);
    }

    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                @Nullable Exception ex) {
        UserContextHolder.clear();
    }

    /**
     * 检查请求是否合法
     */
    private boolean check(Object handler, HttpServletRequest request, HttpServletResponse response) throws Exception {
        UserInfoContext userInfoContext = UserServerRpc.currentUser(request);
        // 将用户信息放入 上下文环境中
        UserContextHolder.set(userInfoContext);
        return true;
    }


    /**
     * 接口是否需要登录
     *
     * @return true表示需要登录, false表示无需登录
     */
    private boolean needLogin(Object handler) {
        if (!(handler instanceof HandlerMethod)) {
            return false;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        PublicApi publicApi = method.getAnnotation(PublicApi.class);
        return publicApi == null;
    }
}

